home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_10_05
/
cmenu13.exe
/
CMENU2.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-06
|
14KB
|
611 lines
/************************************************************
* Program: CMENU Menu Compiler
* Module: cmenu2.c
* Menu Compiler:
* Menu/Item Token Processing Functions
* Written by: Leor Zolman, 7/91
************************************************************/
#include "cmenu.h"
#include "ccmenu.h"
#if __STDC__
#pragma hdrstop
#endif
#include <ctype.h>
/************************************************************
* do_menu():
* Process the MENU keyword
************************************************************/
int do_menu()
{
int tok;
if (in_menu) /* Are we currently processing a menu? */
{ /* yes. */
warning("Endmenu missing from previous menu");
do_endmenu(); /* give them the benefit of the doubt */
}
if ((tok = gettok()) != T_STRING)
{
if (n_menus)
error("Menu name missing; menu unreachable");
sprintf(tparam, "menu%d", n_menus + 1); /* force a name */
ungettok(tok);
}
if (strlen(tparam) > MAX_NAME)
{
error("The name '%s' is too long (%d chars max)",
tparam, MAX_NAME);
tparam[MAX_NAME] = '\0'; /* truncate name */
}
if ((MIp = find_menu(tparam)) == NULL) /* menu exist? */
{
MInfo[n_menus] = create_menu(tparam); /* no. */
if (fatal)
return ERROR; /* creation error */
else
MIp = &MInfo[n_menus++]; /* OK, bump count */
}
else
if (MIp -> Processed) /* redefinition? */
return fatalerr("Duplicate Menu definition"); /* yes. */
Mp = &MIp -> Menu;
*Mp->title = *Mp->path = '\0';
Mp->nitems = Mp->widest = 0;
Mp->spacing = Mp->columns = Mp->escape = DEFAULT;
Mp->align = DEFAULT;
in_item = FALSE; /* state variables describing the */
in_menu = TRUE; /* current menu being processed */
n_items = 0;
n_refs = 0; /* no forward item references yet */
if ((tok = gettok()) != T_COLON) /* optional colon */
ungettok(tok);
return OK;
}
/************************************************************
* do_title():
* Process the TITLE clause for a menu.
************************************************************/
int do_title()
{
int tok;
if ((tok = gettok()) != T_STRING)
{
error("Title text missing");
ungettok(tok);
}
if (!in_item) /* Before all items? */
{ /* yes. */
if (*Mp->title)
return error("A Menu Title has already been specified");
if (strlen(tparam) > MAX_TXTWID - 1)
return error("Menu Title is too long (max %d chars)",
MAX_TXTWID-1);
strcpy(Mp->title, tparam);
}
else
return error("The Menu Title must precede all Menu Items.");
return OK;
}
/************************************************************
* do_path():
* Process the PATH option.
* Note that the PATH option may apply to an entire
* menu or just to a single menu item (determined
* by context.)
************************************************************/
int do_path()
{
int tok;
char c, *cp;
if ((tok = gettok()) != T_STRING)
{
error("Path text missing");
ungettok(tok);
}
if ((c = tparam[strlen(tparam) - 1]) == '/' || c == '\\') /* delete */
tparam[strlen(tparam) - 1] = '\0'; /* traling slash */
if (strlen(tparam) > MAX_PATH - 1)
return error("The specified path is too long (max %d chars)",
MAX_PATH - 1);
if (!in_item) /* Referring to the menu? */
{ /* yes. */
if (*Mp->path)
return error("A Menu Path has already been specified");
strcpy(Mp->path, tparam);
}
else
{ /* Must be for the item. */
if (*Ip->path)
return error("An Item Path has already been specified");
strcpy(Ip->path, tparam);
}
return OK;
}
/************************************************************
* do_align():
* Process text alignment option.
* Note: this option is a no-op. I decided there wasn't
* any real need for any other than left-justified item
* alignment. But, in case anyone thinks of a use for it,
* I'm leaving in the ability to process the option.
************************************************************/
int do_align()
{
int tok;
if (in_item)
return error("The Align clause must precede all Menu Items.");
if (Mp->align)
return error("Align option already specified for this menu");
switch (tok = gettok())
{
case T_LEFT:
Mp->align = 'L';
break;
case T_RIGHT:
Mp->align = 'R';
break;
case T_CENTER:
Mp->align = 'C';
break;
default:
ungettok(tok);
return error("Align missing valid modifier");
}
return OK;
}
/************************************************************
* do_spacing():
* Process the SPACING option (applies
* to menus only.)
************************************************************/
int do_spacing()
{
int tok;
if ((tok = gettok()) != T_VALUE)
{
error("Spacing value missing");
ungettok(tok);
}
if (in_item)
return error("Spacing option must precede all menu items");
if (Mp->spacing)
return error("Spacing option already specified");
/* only single and double spacing supported */
if (vparam != 1 && vparam != 2)
return error("Spacing value must be either 1 or 2");
Mp->spacing = vparam;
return OK;
}
/************************************************************
* do_columns():
* Process the COLUMNS option
************************************************************/
int do_columns()
{
int tok;
if ((tok = gettok()) != T_VALUE)
{
error("Columns value missing");
ungettok(tok);
}
if (in_item)
return error("Columns option must precede all menu items");
if (Mp->columns)
return error("Columns option already specified");
if (vparam < 1 || vparam > 6) /* 6 seems a reasonable max. */
return error("Columns value must be between 1 and 6");
Mp->columns = vparam;
return OK;
}
/************************************************************
* do_escape():
* Process "escape" and "noescape" menu options
************************************************************/
int do_escape()
{
if (in_item)
return error("\"%s\" must appear before all menu items",
keywords[token].keyword);
if (Mp->escape)
return error("Escape option already specified");
Mp->escape = (token == T_ESCAPE) ? YES : NO;
return OK;
}
/************************************************************
* do_endmenu():
* Process ENDMENU keyword
************************************************************/
int do_endmenu()
{
int i;
if (!n_items)
error("No menu items specified for this menu");
for (i = 0; i < n_refs; i++) /* check for unresolved */
{ /* forward Item references */
if (*fwd_refs[i].refp == UNDEF_FWD)
{
int save_lineno = lineno;
lineno = fwd_refs[i].lineno;
error("Unresolved reference to Item \"%s\"",
fwd_refs[i].iname);
lineno = save_lineno;
}
}
in_menu = in_item = FALSE; /* done with current menu */
MIp -> Processed = TRUE; /* it is now processed */
Mp -> nitems = n_items;
return OK;
}
/************************************************************
* do_item():
* Process the ITEM clause. Create a new ite
* and fill in any existing forward references to it.
************************************************************/
int do_item()
{
int tok, i;
char *cp, c;
if (n_items)
itemcheck(); /* check for previous item's completion */
if ((tok = gettok()) != T_STRING) /* label specified? */
{ /* If not, stuff unique */
sprintf(tparam,"dummy!%d", n_items); /* dummy name in */
ungettok(tok);
}
else
{
if (strlen(tparam) > MAX_NAME)
{
error("Item name \"%s\" too long. Max %d chars.",
tparam, MAX_NAME);
tparam[MAX_NAME] = '\0';
}
else for (cp = tparam; c = *cp; cp++)
if (!(isalpha(c) || isdigit(c) || c == '_'))
{
error("Invalid char in identifier name: \"%s\"",
tparam);
*cp = '\0';
break;
}
}
if ((IIp = find_item(tparam)) != NULL) /* Item name found? */
return error("